#usr/bin/python



from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtCore import Qt, QMetaType
from parsers import element_parser, KEGG_parser,MetJP_parser, Biocyc_parser
from model import identification_peaks
from core import pySpec as obj
from gui import table_view
from controller import table_view_control
import sys
import os
import os.path as path
from controller import ControllerDialog as dial

class id_thread(QtCore.QThread):
	"""Identifiaction thread"""
	
	def __init__(self, lspl, mmu, charge, hit, alphabet, databases,data,  main_window = None):#,
		"""
		Constructor
		handles databases, mmu, spl
		"""
		QtCore.QThread.__init__(self, main_window)
		#self.spl =spl
		self.lspl =lspl
		self.mmu =mmu
		self.charge= charge
		self.hit = hit
		self.alphabet =alphabet
		self.databases= databases
		self.data =data
		self.main_window = main_window
	
	def emission(self, value):
		self.emit(QtCore.SIGNAL("update_pb"), value)
		
	def run(self):
		"""
		Thread Actions
		identifcation instance
		"""
		for i, spl in enumerate(self.lspl):
			if isinstance(spl,  obj.Sample):
				table_id  = QtGui.QStandardItemModel( 1, 2)
				id_ =identification_peaks.identification_peaks(spl.get_mapped_peaks(), self.mmu, self.charge, self.alphabet, self.databases, \
						self.data, spl.get_id_model())#spl.get_id_model()
				self.connect(id_, QtCore.SIGNAL("update_pb"), self.emission)
				id_.identification(self.hit, error=5)
				self.emit(QtCore.SIGNAL("sent_spl"), spl, self.charge)#get_id_model
				
			elif isinstance(spl, obj.RawPeakList):
				id_model = QtGui.QStandardItemModel(1, 2)
				id_model.setHorizontalHeaderLabels =["RT", "mass", "mmu", "formulas","score", "KEGG","name", "MEtabolomeJP","name"]
				id_ =identification_peaks.identification_peaks(spl, self.mmu, self.charge, self.alphabet, self.databases, \
						self.data, id_model)
				id_.identification(self.hit, error=5)
				self.emit(QtCore.SIGNAL("sent_model"),  id_model)
		
	def begin(self):
		"""
		launches the thread
		"""
		self.start()
		self.exec_()
		


		
class identif_control(dial):

	"""Class for handling identification gui"""
	
	attributes =('elements', 'kegg_file', 'metjp_file', 'biocyc_file')
	
	def __init__(self, lspl,visu):
		"""constructor """
		dial.__init__(self, lspl, visu)
		
		#databases
		self.databases ={"KEGG":0, "METJP":0, "BIOCYC":0}
		
		#needed files
		self.elements_file =path.normcase("config/elements.xml")
		self.kegg_file =path.normcase("config/KEGG.txt")
		self.metjp_file =path.normcase("config/metaboliteMass.txt")
		self.biocyc_file =path.normcase( "config/LinkBioCycKegg.txt")
		
		#initialization methods
		self.visu.initialize()
		

		#connections
		QtCore.QObject.connect( self.visu.pushButton, QtCore.SIGNAL ( "clicked () " ), self.printing)
		QtCore.QObject.connect( self.visu.pushButton_2, QtCore.SIGNAL ( "clicked()" ), self.dialog)
		QtCore.QObject.connect(self.visu.buttonBox, QtCore.SIGNAL("accepted()"),self.Identification)

	
	def get_databases(self, kegg,  met_jp, biocyc):
		""" parse all files"""
		#KEGG
		if kegg:
			self.visu.parent().statusBar().showMessage("Parsing Kegg file", 2000)
			kegg_ = KEGG_parser.kegg_parser(self.kegg_file)
			self.databases["KEGG"] = kegg_.parsing()
		#METJP
		if met_jp:
			self.visu.parent().statusBar().showMessage("Parsing Met_JP file", 2000)
			metjp_ =MetJP_parser.met_jp_parser(self.metjp_file)
			self.databases["METJP"] = metjp_.parsing()
		#BIOCYC
		if biocyc:
			self.visu.parent().statusBar().showMessage("Parsing BioCyc file", 2000)
			biocyc_parser = Biocyc_parser.BioCyc_parser(self.biocyc_file)
			self.databases["BIOCYC"] = biocyc_parser.parsing()
	
	def Identification(self):
	
		"""Main Function"""
		#if self.visu.parent().pb.value():
		#	self.visu.parent().pb.setValue(0)
		
		#get files to treat
		filename_to_process = self.visu.lineEdit.text().split(';')
		masses = str(self.visu.le.text()).split(';')
		
		#get parameters values
		charge = float(self.visu.spinBox.text())
		mmu =float(self.visu.lineEdit_2.text())
		hits = self.visu.spin_hit.value()
		
		#manages alphabet
		wanted_alphabet = str(self.visu.lineEdit_3.text())
		
		#manages checking
		kegg_checked = self.visu.checkBox.isChecked()
		met_jp_checked = self.visu.checkBox_2.isChecked()
		biocyc_checked = self.visu.checkBox_5.isChecked()
		
		idms = self.visu.checkBox_4.isChecked()
		phos = self.visu.checkBox_6.isChecked()
		smiles_checked =self.visu.checkBox_7.isChecked()
		self.visu.close()
		
		if  smiles_checked and not biocyc_checked:
			self.visu.parent().ShowInformationMessage("One more check needed", "In order to use smiles information, Biocyc checkbox must be checked")
			return
		#get databases
		self.get_databases(kegg_checked, met_jp_checked, biocyc_checked)
			
		#correction of the alphabet wanted
		el = element_parser.element_parser(self.elements_file, wanted_alphabet)
		self.visu.parent().statusBar().showMessage("Parsing Elements file", 2000)
		new_alphabet = el.parsing()
					
		#creation of a new lspl object containing all the filenames to treat
		lspl = obj.ListSample()
		for xml in filename_to_process:
			if xml not in self.lspl.getFiles():
				self.visu.parent().ShowErrorMessage("Error","-"+xml+"-,does not exist, the first field should not be empty:you must parse before")
				return
			lspl.append(self.lspl.Sample(xml))
			
		if masses[0] =="":
	#launch the algorithm
	#try threading !!!
			#for spl in lspl:
			a = id_thread( lspl, mmu, charge, hits, new_alphabet, self.databases, self.visu.data, self.visu.parent())
			QtCore.QObject.connect(a, QtCore.SIGNAL("sent_spl"),self.updateMdiArea)
			QtCore.QObject.connect(a, QtCore.SIGNAL("update_pb"),self.visu.parent().update_progress_bar)
			a.begin()
		else:
			pkl = lspl.Sample(filename_to_process[0]).get_peak_list()
			wanted_peaks =obj.RawPeakList()
			for mass in masses:
				wanted_peaks.append(pkl.peaklist_at_trans(float(mass)))
			print "wanted_peaks", len(wanted_peaks)
			#in this case just pass masses and not peaks
			a= id_thread(wanted_peaks, mmu, charge, hits, new_alphabet, self.databases, self.visu.data,  self.visu.parent())
			QtCore.QObject.connect(a, QtCore.SIGNAL("sent_model"),self.addModel)
			a.begin()
			
		#remove the unuseful file
		if os.path.exists("HR2_output.txt"):
			os.remove("HR2_output.txt")
				
	
	def addModel(self, id_model):
		print "signal pass"
		view = QtGui.QTableView()
		view.setModel(id_model)
		self.visu.parent().addMdiSubWindow(view, "Identification List of masses")


	def updateMdiArea(self, spl, charge):
		"""Add the model to the view when the thread ended"""
		
		view =table_view.TableView(spl.get_id_model())#QtGui.QTableView()
		control = table_view_control.table_control(view,  spl, charge)
		#delegate = CustomItemDelegate(view)
		#view.table_view.setItemDelegate(delegate)
		self.visu.parent().addMdiSubWindow(view)
		view.exec_()
		#view.setSortingEnabled(True)




class CustomItemDelegate(QtGui.QItemDelegate):
	"""Special class for drawing colored cells in the table view"""
	
	def __init__(self, parent):
		"""Constructor, empty just want to define paintEvent method"""
		
		QtGui.QStyledItemDelegate.__init__(self, parent)
		
	def paint(self,  painter, option, index):
		"""have to be reimplemented"""
		
		value = index.data(QtCore.Qt.DisplayRole)
		if value != "":
			painter.setPen(QtGui.QColor(Qt.green))
			painter.setOpacity(.5)
			painter.drawRect(option.rect)
			painter.fillRect(option.rect, QtGui.QColor(Qt.green))
		else:
			painter.setPen(QtGui.QColor(Qt.red))
			painter.setOpacity(.5)
			painter.drawRect(option.rect)
			painter.fillRect(option.rect, QtGui.QColor(Qt.red))
		
		if value.isValid():
			painter.setPen(QtGui.QColor(Qt.black))
			text = value.toString()
			painter.drawText(option.rect, Qt.AlignLeft, text)
	
	
